package service

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"shop-bean/constant"
	"shop-bean/model"
	"shop-bean/vo"
	"shop-common/library/variables"
	"shop-common/utils/queryWrapper"
	"shop-service/repository"
	"time"
)

type ICategoryService interface {
	FindById(ctx context.Context, id uint) (category *model.Category, err error)
	FindOne(ctx context.Context, pair *queryWrapper.WherePair) (category *model.Category, err error)
	Find(ctx context.Context, shopId, _type int) ([]*vo.CategoryVO, error)
	FindByParentId(ctx context.Context, parentId uint) ([]*vo.CategoryVO, error)
	Create(ctx context.Context, category *model.Category, fileId uint) error
	Updates(ctx context.Context, category *model.Category, oldPic string) error
	Delete(ctx context.Context, categoryId uint, oldPic string) error
}

type CategoryService struct {
	db                *gorm.DB
	repository        repository.ICategoryRepository
	attachFileService IAttachFileService
}

func NewCategoryService(
	AttachFileService IAttachFileService,
	repository repository.ICategoryRepository,
) ICategoryService {
	return &CategoryService{variables.GormDB(), repository, AttachFileService}
}

func (s *CategoryService) Find(ctx context.Context, shopId, _type int) ([]*vo.CategoryVO, error) {
	category, err := s.repository.Find(s.db, shopId, _type)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "find category failed: err %v, shopId: %d", err, shopId)
		return nil, err
	}
	return category, nil
}

func (s *CategoryService) FindById(ctx context.Context, id uint) (*model.Category, error) {
	category, err := s.repository.FindById(s.db, id)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "findById category categoryId failed: err %v, categoryId %d", err, id)
		return nil, err
	}
	return category, nil
}

func (s *CategoryService) FindByParentId(ctx context.Context, parentId uint) (categoryDTOs []*vo.CategoryVO, err error) {
	categoryDTOs, err = s.repository.FindByParentId(s.db, parentId)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "findByParentId categoryDTOs failed: err %v, parentId %v", err, parentId)
		return nil, err
	}

	return categoryDTOs, nil
}

func (s *CategoryService) Create(ctx context.Context, category *model.Category, fileId uint) error {
	return s.db.Transaction(func(tx *gorm.DB) error {
		if err := s.repository.Create(tx, category); err != nil {
			variables.Logger.Errorf(ctx, "create category failed: err %v, category %+v", err, category)
			return err
		}

		if fileId > 0 {
			// 正常
			if err := s.attachFileService.UpdateBatchAttachFileStatus(ctx, tx, []uint{fileId}, constant.FILE_NORMAL); err != nil {
				return err
			}
		}

		//todo
		if err := insertBrandsAndAttributes(category); err != nil {
			return err
		}

		return nil
	})
}

func insertBrandsAndAttributes(*model.Category) error {
	//保存分类与品牌信息

	//保存分类与参数信息
	return nil
}

func (s *CategoryService) Updates(ctx context.Context, category *model.Category, oldPic string) error {
	columns := map[string]interface{}{
		"pic":           category.Pic,
		"category_name": category.CategoryName,
		"parent_id":     category.ParentId,
		"status":        category.Status,
		"att_ids":       category.AttIds,
		"updated_at":    time.Now(),
	}

	if err := s.repository.Updates(s.db, category.CategoryId, columns); err != nil {
		variables.Logger.Errorf(ctx, "updates category failed: err %v, category %+v", err, category)
		return err
	}

	// 删除旧图片
	if oldPic != "" {
		if err := s.attachFileService.DeleteBatchExpire(ctx, []string{oldPic}); err != nil {
			return err
		}
	}

	// 新图片
	if category.FileId > 0 {
		// 正常
		if err := s.attachFileService.UpdateBatchAttachFileStatus(ctx, s.db, []uint{category.FileId}, constant.FILE_NORMAL); err != nil {
			return err
		}
	}
	return nil
}

func (s *CategoryService) Delete(ctx context.Context, categoryId uint, oldPic string) error {
	err := s.repository.Delete(s.db, categoryId)
	if err != nil {
		variables.Logger.Errorf(ctx, "delete category failed: err %v, categoryId %d", err, categoryId)
		return err
	}

	if err := s.attachFileService.DeleteBatchExpire(ctx, []string{oldPic}); err != nil {
		return err
	}

	return nil
}

func (s *CategoryService) FindOne(ctx context.Context, pair *queryWrapper.WherePair) (*model.Category, error) {
	category, err := s.repository.FindOne(s.db, pair)
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		variables.Logger.Errorf(ctx, "find by pair category failed: err %v, pair %+v", err, pair)
		return nil, err
	}
	return category, nil
}
